import {Vue, Component, Prop} from 'vue-property-decorator';

@Component({})
export default class CameraComponent extends Vue {
    @Prop({default: true}) public isIdCardFront: boolean | undefined; // 是否拍摄身份证正面
    public isCameraComponentShow = false;
    public isPreviewPhoto = false; // 控制画布是否显示
    private canvas: any; // 画布节点
    private context: any; // 画布对象
    private video: any; // 视频节点
    private resolutionRatio: ResolutionRatioInterface = {width: 1280, height: 720}; // 获取摄像头像素比
    private ratio = 0.5; // 缩放比例

    /**
     * 照相机组件显示
     */
    public showCameraComponent(): void {
        this.isCameraComponentShow = true;
        this.$nextTick(() => {
            this.init();
        });
    }

    /**
     * 组件相机隐藏
     */
    public hideCameraComponent(): void {
        this.isCameraComponentShow = false;
    }

    /**
     * 拍摄照片
     */
    public onClickTakePhoto() {
        this.isPreviewPhoto = true;
        this.$nextTick(() => {
            const {width, height} = this.resolutionRatio;
            const {ratio} = this;
            const cur_ratio = (height * ratio) / (height * 0.5);
            this.canvas = document.getElementById('photoCanvas');
            this.context = this.canvas.getContext('2d');
            this.canvas.width = height * ratio;
            this.canvas.height = width * ratio;
            this.context.save();
            this.context.rect(50 * cur_ratio, 56 * cur_ratio, 263 * cur_ratio, 410 * cur_ratio);
            this.context.stroke();
            this.context.clip(); // 剪裁身份证位置
            this.context.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
            const imgData = this.context.getImageData(50 * cur_ratio, 56 * cur_ratio, 263 * cur_ratio, 410 * cur_ratio);
            this.canvas.width = 263 * cur_ratio;
            this.canvas.height = 410 * cur_ratio;
            this.context.putImageData(imgData, 0, 0, 0, 0, 263 * cur_ratio, 410 * cur_ratio);
        });
    }

    /**
     * 点击取消保存照片
     */
    public onClickCancelSavePhoto(): void {
        this.isPreviewPhoto = false;
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }

    /**
     * 点击保存照片
     */
    public onClickSavePhoto(): void {
        console.log('图像', this.canvas.toDataURL());
        this.$emit('onClickSavePhoto', {
            base64Url: this.canvas.toDataURL()
        });
    }

    /**
     * 点击返回按钮
     */
    public onClickBackBtn(): void {
    }

    private mounted(): void {
        this.showCameraComponent();
    }

    /**
     * 页面初始化
     */
    private init(): void {
        this.oldBrowser();
        this.video = document.getElementById('cameraVideo');
        if (navigator.mediaDevices.getUserMedia) {
            // @ts-ignore
            if (window.stream) {
                // @ts-ignore
                window.stream.getTracks().forEach((track: any) => {
                    track.stop();
                });
            }
            const constraints = {
                audio: false,
                video: {
                    ...this.resolutionRatio, // 摄像头分辨率
                    facingMode: {
                        exact: 'environment', // 环境摄像头
                    },
                },
            }; // 强制打开后置摄像头
            // const constraints = {audio: true, video: true}; // 电脑调试打开默认摄像头
            navigator.mediaDevices.getUserMedia(constraints).then(
                (stream) => {
                    if (window.URL) {
                        this.video.srcObject =  stream;
                    } else {
                        // @ts-ignore
                        this.video.src = stream;
                    }
                    // @ts-ignore
                    window.stream = stream;
                },
            ).catch(
                error => {
                    // alert(JSON.stringify(error));
                },
            );
        } else {
            // alert('不支持');
        }
    }

    private oldBrowser() {
        // 老的浏览器可能根本没有实现 mediaDevices，所以我们可以先设置一个空的对象
        if (navigator.mediaDevices === undefined) {
            // @ts-ignore
            navigator.mediaDevices = {};
        }

        //  一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia
        //  因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。
        if (navigator.mediaDevices.getUserMedia === undefined) {
            navigator.mediaDevices.getUserMedia = (constraints) => {

                // 首先，如果有getUserMedia的话，就获得它
                // @ts-ignore
                const getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

                // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
                if (!getUserMedia) {
                    return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
                }

                // 否则，为老的navigator.getUserMedia方法包裹一个Promise
                return new Promise(function (resolve, reject) {
                    getUserMedia.call(navigator, constraints, resolve, reject);
                });
            };
        }
    }
}

interface ResolutionRatioInterface {
    width: number;
    height: number;
}
